/***************************************************************************
 *   oboe.utils.JapiController                                             *
 *   Copyright (C) 2011 by Felipe Manga                                    *
 *   lufeboma@gmail.com                                                    *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

package oboe.utils
{
	import com.adobe.crypto.MD5;
	import com.adobe.serialization.json.JSON;
	import com.adobe.serialization.json.JSONParseError;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.system.Security;
	import flash.utils.Dictionary;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	import oboe.core.Oboe;
	
	public dynamic class JapiController extends Proxy
	{
		private var loaders : Dictionary;
		private var loaderCount : int = 0;
		private var japiacc:int = 0;
		
		public static var viewClass : Class;
		
		public function JapiController()
		{
			super();
			this.loaders = new Dictionary();
		}		
		
		flash_proxy override function callProperty( name:*, ...rest ):*
		{
			var func : Function = rest[0] as Function;
			var req : URLRequest = new URLRequest( Oboe.flags["PARAISO"] );
			var json : String = "{\"" + name + "\":[";
			var hash : String = "";
			for( var i:int = (func==null)?0:1; i<rest.length; ++i ){
				
				if( rest[i] is String )
				{
					json += "\"" + rest[i] + "\"";
					hash += String(rest[i]); //  + String(i);
				}
				else if( rest[i] is Boolean )
				{
					var bval:String;
					if( rest[i] ) bval = "1";
					else bval = "0";
					json += bval;
					hash += bval;
				}
				else if( rest[i] is int || rest[i] is Number || rest[i] is uint ){
					json += String(rest[i]);
					hash += String(rest[i]);
				}
				else
				{
					var val:String = JSON.encode( rest[i] ); 
					json += val;
					hash += val;
				}
				json += ",";
			}
			json += "\"" + MD5.hash( hash );
			json += "\"]}";
			
			json = "japi=" + escape(json);
			var callCB:Function = function( data:* ):void{
				if( func != null ){
					var str : String = data;
					var ret : Object = str;
					try{
						ret = JSON.decode( str )[0];
					}catch( x:JSONParseError ){
						trace( ret = x.message + "\n" + str );
					}
					if( Oboe.flags.DEBUG )
					{
						func ( ret );
					}
					else
					{
						try
						{
							func ( ret );
						}
						catch( err:Object )
						{
							if( Oboe.flags.errorHandler ) Oboe.flags.errorHandler( err );
						}
					}
				}else{
					trace( "Ignoring response: ", data );
				}
			};
			
			if( Oboe.flags.USE_JS_PROXY )
			{
				Security.allowDomain("*");
				var cbn:String = "japi_" + (japiacc++);
				ExternalInterface.addCallback( cbn, callCB );
				ExternalInterface.call( "(function(url){ oboe.getTextFile(url, function(data){ document.getElementById('" + ExternalInterface.objectID + "')." + cbn + "(data.replace(/[\\x00-\\x1F]/g, '')); }); })", req.url + "/?" + json );
			}
			else
			{
				req.data = new URLVariables( json );
				req.method = URLRequestMethod.POST;
				var ldr : URLLoader = new URLLoader();
				ldr.addEventListener( Event.COMPLETE,
					function ( e:Event ) : void {
						delete loaders[e.target];
						loaderCount--;
						callCB( URLLoader(e.target).data );
					}
				);
				ldr.addEventListener( IOErrorEvent.IO_ERROR, 
					function ( e:Event ) : void {
						delete loaders[e.target];
						loaderCount--;
						trace("URL Request failed.");
						if( func != null ){
							func ( null );
						}
					}
				);
				Object(ldr).loadEx( req );
				loaders[ldr] = ldr;
				loaderCount++;
			}
		}
	}
	
}